package com.fancy.gateway.filter;

import com.fancy.common.dto.response.Result;
import com.fancy.gateway.util.JwtUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * 管理员认证过滤器
 *
 * @author fancy
 */
@Slf4j
@Component
public class AdminAuthenticationFilter extends AbstractGatewayFilterFactory<AdminAuthenticationFilter.Config> {

    @Autowired
    private JwtUtils jwtUtil;

    @Autowired
    private ObjectMapper objectMapper;
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Value("${auth.admin-paths}")
    private String adminPathsStr;

    public AdminAuthenticationFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();

            log.debug("处理管理员请求路径: {}", path);

            // 获取Token
            String authHeader = request.getHeaders().getFirst("Authorization");
            String token = jwtUtil.getTokenFromHeader(authHeader);

            if (token == null) {
                log.warn("管理员接口未提供认证Token: {}", path);
                return buildErrorResponse(exchange, 40101, "请重新登录");
            }

            // 验证Token
            if (!jwtUtil.validateToken(token)) {
                log.warn("管理员接口Token验证失败: {}", path);
                return buildErrorResponse(exchange, 40101, "请重新登录");
            }

            // 检查Token是否过期
            if (jwtUtil.isTokenExpired(token)) {
                log.warn("管理员接口Token已过期: {}", path);
                return buildErrorResponse(exchange, 40101, "请重新登录");
            }

            // 检查管理员权限
            if (!jwtUtil.isAdmin(token)) {
                String userId = jwtUtil.getUserIdFromToken(token);
                String role = jwtUtil.getUserRoleFromToken(token);
                log.warn("管理员权限不足: userId={}, role={}, path={}", userId, role, path);
                return buildErrorResponse(exchange, 40301, "无管理员权限");
            }

            // 添加管理员信息到请求头
            ServerHttpRequest modifiedRequest = request.mutate()
                    .header("X-User-Id", jwtUtil.getUserIdFromToken(token))
                    .header("X-Username", jwtUtil.getUsernameFromToken(token))
                    .header("X-User-Role", jwtUtil.getUserRoleFromToken(token))
                    .header("X-Is-Admin", "true")
                    .build();

            log.debug("管理员认证成功: userId={}, path={}", jwtUtil.getUserIdFromToken(token), path);

            return chain.filter(exchange.mutate().request(modifiedRequest).build());
        };
    }

    /**
     * 解析配置中的路径列表
     */
    private List<String> parsePathList(String pathsStr) {
        if (pathsStr == null || pathsStr.trim().isEmpty()) {
            return Arrays.asList();
        }
        return Arrays.asList(pathsStr.split(","));
    }

    /**
     * 构建错误响应
     */
    private Mono<Void> buildErrorResponse(ServerWebExchange exchange, int code, String message) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.FORBIDDEN);
        response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);

        Result<Object> result = Result.fail(code, message);

        try {
            String body = objectMapper.writeValueAsString(result);
            DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(buffer));
        } catch (JsonProcessingException e) {
            log.error("构建管理员错误响应失败", e);
            return response.setComplete();
        }
    }

    public static class Config {
        // 配置参数类
    }
}
